#include "widget_script_editor.h"
#include "ui_widget_script_editor.h"
#include <Qsci/qsciapis.h>
#include "../Program.h"
#include "../AvatarLibrary.h"
#include "../utility/AvatarLuaLexer.h"
#include <QMenu>
#include <QColorDialog>

WidgetScriptEditor::WidgetScriptEditor(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::WidgetScriptEditor)
    , _initialized(false)
    , _currentScriptIndex(-1)
{
    ui->setupUi(this);
    // 光标以及矩形选择
    ui->editor->SendScintilla(QsciScintilla::SCI_SETCODEPAGE, QsciScintilla::SC_CP_UTF8);
    ui->editor->setCaretForegroundColor(Qt::white);
    ui->editor->setCaretLineBackgroundColor(QColor::fromRgb(0x282828));
    ui->editor->setCaretLineVisible(true);
    ui->editor->setSelectionForegroundColor(QColor::fromRgb(0xFE9000));
    ui->editor->setSelectionBackgroundColor(QColor::fromRgb(0x114D9C));
    ui->editor->SendScintilla(QsciScintilla::SCI_SETMULTIPLESELECTION, true);
    ui->editor->SendScintilla(QsciScintilla::SCI_SETVIRTUALSPACEOPTIONS, QsciScintilla::SCVS_RECTANGULARSELECTION);
    ui->editor->SendScintilla(QsciScintilla::SCI_SETADDITIONALSELECTIONTYPING, true);
    ui->editor->SendScintilla(QsciScintilla::SCI_SETMOUSEDWELLTIME, 1000);
    // 边界栏(行号+折叠区)
    ui->editor->setMarginType(0, QsciScintilla::NumberMargin);
    ui->editor->setMarginWidth(0, 30);
    ui->editor->setMarginMarkerMask(0, 0);
    ui->editor->setFolding(QsciScintilla::BoxedTreeFoldStyle, 1);
    ui->editor->setMarginsForegroundColor(QColor::fromRgb(0xB7B7B7));
    ui->editor->setMarginsBackgroundColor(QColor::fromRgb(0x2A211C));
    ui->editor->setFoldMarginColors(QColor::fromRgb(0x2A211C), QColor::fromRgb(0x2A211C));
    // 缩进
    ui->editor->setEolMode(QsciScintilla::EolUnix);
    ui->editor->setTabWidth(4);
    ui->editor->setAutoIndent(true);
    ui->editor->setIndentationsUseTabs(true);
    ui->editor->setIndentationGuides(true);
    ui->editor->setIndentationGuidesForegroundColor(QColor::fromRgb(0xB7B7B7));
    ui->editor->setIndentationGuidesBackgroundColor(QColor::fromRgb(0x2A211C));
    // 右键菜单
    ui->editor->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->editor, &QsciScintilla::customContextMenuRequested, this, &WidgetScriptEditor::on_customContextMenuRequested);
    // 初始化编辑器状态
    ui->editor->clear();
    ui->editor->setModified(false);
    this->setVisible(false);
}

WidgetScriptEditor::~WidgetScriptEditor()
{
    delete ui;
}

/**
 * @brief 初始化脚本编辑器
 */
void WidgetScriptEditor::Initialize()
{
    if (_initialized) return;
    _initialized = true;
    // 词法解析器
    QsciLexerLua* lexer = new AvatarLuaLexer(this);
    lexer->setFoldCompact(false);
    lexer->setDefaultFont(QFont("Consolas", 12));
    lexer->setDefaultColor(QColor::fromRgb(0xFFFFFF));
    lexer->setDefaultPaper(QColor::fromRgb(0x212121));
    lexer->setColor(QColor::fromRgb(0xD0DAE2), QsciLexerLua::Identifier);
    lexer->setColor(QColor::fromRgb(0xBD758B), QsciLexerLua::Comment);
    lexer->setColor(QColor::fromRgb(0x40BF57), QsciLexerLua::LineComment);
    lexer->setColor(QColor::fromRgb(0xFFFF00), QsciLexerLua::Number);
    lexer->setColor(QColor::fromRgb(0xFFFF00), QsciLexerLua::String);
    lexer->setColor(QColor::fromRgb(0xE95454), QsciLexerLua::Character);
    lexer->setColor(QColor::fromRgb(0x8AAFEE), QsciLexerLua::Preprocessor);
    lexer->setColor(QColor::fromRgb(0xE0E0E0), QsciLexerLua::Operator);
    lexer->setColor(QColor::fromRgb(0x48A8EE), QsciLexerLua::Keyword);
    lexer->setColor(QColor::fromRgb(0xF98906), QsciLexerLua::BasicFunctions);
    lexer->setColor(QColor::fromRgb(0xF98906), QsciLexerLua::StringTableMathsFunctions);
    lexer->setColor(QColor::fromRgb(0xF98906), QsciLexerLua::CoroutinesIOSystemFacilities);
    lexer->setColor(QColor::fromRgb(0x4EC9B0), QsciLexerLua::KeywordSet5);
    lexer->setColor(QColor::fromRgb(0x92DE5C), QsciLexerLua::KeywordSet6);
    ui->editor->setLexer(lexer);
    // 加载脚本文档
    _docProcess.LoadAvatarDoc();
    _docProcess.LoadPluginDoc();
    _docProcess.LoadSceneDoc();
    // 自动补全
    ui->editor->setAutoCompletionSource(QsciScintilla::AcsAll);
    ui->editor->setAutoCompletionCaseSensitivity(true);
    ui->editor->setAutoCompletionThreshold(1);
    ui->editor->SendScintilla(QsciScintilla::SCI_AUTOCSETMAXHEIGHT, 20);
    ui->editor->setCallTipsStyle(QsciScintilla::CallTipsNoContext);
    ui->editor->setCallTipsVisible(20);
    ui->editor->setCallTipsBackgroundColor(Qt::yellow);
    ui->editor->setCallTipsHighlightColor(Qt::red);
    QsciAPIs* apis = new QsciAPIs(lexer);
    _docProcess.AddAPI(apis);
    apis->prepare();
    // 场景节点方法调用提示
    apis->setUserApiCallback([=](int commas, const QMap<QString, QStringList>& entry, QStringList& result){
        if (commas == 1)
        {
            int line, index;
            QString nodeType;
            ui->editor->getCursorPosition(&line, &index);
            QString lineStr = ui->editor->text(line);
            qsizetype start = lineStr.lastIndexOf('(', index) + 1;
            QString nodeName = lineStr.mid(start, lineStr.lastIndexOf(',', index) - start).trimmed();
            AvatarLibrary::avatar_execute("return scene.type(" + nodeName + ")", nodeType);
            ui->editor->autoCompleteFromUser(entry[nodeType]);
            result.clear();
        }
    });
}

/**
 * @brief 新增或修改GUI脚本
 * @param type
 * @param name
 * @param desc
 * @param evt
 */
void WidgetScriptEditor::EditGui(const QString &type, const QString &name, const QString &desc, const QString& evt)
{
    int line, index;
    ui->editor->getCursorPosition(&line, &index);
    if (evt.isEmpty()) ui->editor->insertAt(QString("gui.create('%1', '%2', '%3')\n").arg(name, type, desc), line, 0);
    else ui->editor->insertAt(QString("gui.create('%1', '%2', '%3', %4)\n").arg(name, type, desc, evt), line, 0);
}

/**
 * @brief 加载脚本到编辑器
 * @param index
 */
void WidgetScriptEditor::loadScript(int index)
{
    if (index < 0)
    {
        _currentScriptIndex = -1;
        ui->editor->setText("");
        ui->editor->setModified(false);
        this->setVisible(false);
    }
    else if (index < Program::UserScript.size())
    {
        saveModify();
        _currentScriptIndex = index;
        ui->editor->setText(Program::UserScript[index].second);
        ui->editor->setModified(false);
        this->setVisible(true);
    }
}

/**
 * @brief 保存已修改
 */
void WidgetScriptEditor::saveModify()
{
    if (ui->editor->isModified() && _currentScriptIndex >= 0 && _currentScriptIndex < Program::UserScript.size())
    {
        Program::UserScript[_currentScriptIndex].second.assign(ui->editor->text());
    }
}

/**
 * @brief 右键菜单
 * @param pos
 */
void WidgetScriptEditor::on_customContextMenuRequested(const QPoint &pos)
{
    QMenu* menu = ui->editor->createStandardContextMenu();
    if (menu)
    {
        menu->addAction(tr("选择颜色"), this, [=](){
            QColor color = QColorDialog::getColor(Qt::white,
                this,
                "请选择颜色",
                QColorDialog::ShowAlphaChannel | QColorDialog::DontUseNativeDialog);
            if (color.isValid())
            {
                QString rgba = QString("#%1%2%3%4")
                    .arg(color.red(), 2, 16, QLatin1Char('0'))
                    .arg(color.green(), 2, 16, QLatin1Char('0'))
                    .arg(color.blue(), 2, 16, QLatin1Char('0'))
                    .arg(color.alpha(), 2, 16, QLatin1Char('0')).toUpper();
                ui->editor->insert(rgba);
            }
        });
        menu->addAction(tr("选择场景节点名"), this, [=](){
            int line, index;
            ui->editor->getCursorPosition(&line, &index);
            QString lineStr = ui->editor->text(line).mid(qMax(index - 1, 0));
            const QChar beginChar = lineStr.length() > 0 ? lineStr.at(0) : '\0';
            const QChar endChar = lineStr.length() > 1 ? lineStr.at(1) : '\0';
            QStringList nameList = Program::SceneNodeList.keys();
            if (beginChar != '\'' && beginChar != '"') for (qsizetype i = 0; i < nameList.size(); i++) nameList[i].prepend('\'');
            if (endChar != '\'' && endChar != '"') for (qsizetype i = 0; i < nameList.size(); i++) nameList[i].append('\'');
            ui->editor->autoCompleteFromUser(nameList);
        });
        menu->setAttribute(Qt::WA_DeleteOnClose);
        menu->popup(QCursor::pos());
    }
}

/**
 * @brief 运行当前行
 */
void WidgetScriptEditor::on_btnRunLine_clicked()
{
    int line, index;
    ui->editor->getCursorPosition(&line, &index);
    AvatarLibrary::avatar_command(ui->editor->text(line));
    AvatarLibrary::avatar_update();
}

/**
 * @brief 运行当前文档
 */
void WidgetScriptEditor::on_btnRunAll_clicked()
{
    QString text = ui->editor->selectedText();
    QString command = text.isEmpty() ? ui->editor->text(): text;
    AvatarLibrary::avatar_command(command);
    AvatarLibrary::avatar_update();
}

/**
 * @brief 文本放大
 */
void WidgetScriptEditor::on_btnZoomIn_clicked()
{
    ui->editor->zoomIn();
}

/**
 * @brief 文本缩小
 */
void WidgetScriptEditor::on_btnZoomOut_clicked()
{
    ui->editor->zoomOut();
}

/**
 * @brief 插入GUI元素
 */
void WidgetScriptEditor::on_btnGuiInsert_clicked()
{
    emit sig_createGui();
}
